package plus.exp;

import java.util.List;

import plus.decl.*;
import plus.stmt.Statement;
import plus.*;
import plus.run.*;
/**
 * This is the most general of the lambda forms.
 * @author me
 *
 */
public final class E_LambdaStmt extends Exp {

	private final int lineNr;
	private final List<String> names;
	private final Subroutine sub;
	private final S_Function arrow;

	public E_LambdaStmt(List<String> names, Statement stmt, int lineNr) {
		this.lineNr = lineNr;
		this.names = names;
		this.sub = new Subroutine(new DeclBucket(), stmt);
		arrow = new S_Function(names.size());
	}

	private DynamicExtent dynex;
	@Override public void threadScope() {
		dynex = new DynamicExtent(VScope.current.dynex.lexLevel+1);
		dynex.setRange(arrow.range);
		VScope.enterProc(dynex);
		int k=0;
		for (String name:names) {
			VScope.current.add_param(name, lineNr, arrow.domain[k]);
			k++;
		}
		sub.threadScope(dynex);
		type = Type.fresh(arrow);
		VScope.exit();
	}

	@Override String impliedName() { return null; }

	@Override String aThis() { return "a lambda form"; }

	@Override public void compilePush() {
		// We have to construct a thunk and leave it on the stack.
		// By reference to the VM, that works this way:
		sub.scheduleCompile();
		Emit.asm(VM.MTH);
		sub.entryPoint.asm();
		
		// If this were targeted at a real computer, I would
		// allocate enough ram to hold all the lambda-lifted
		// values, copy said values into place, and the first
		// few bytes become a jsr to the actual function. Now
		// a simple function-call results in the stack holding
		// a pointer to the captured data, and you can even pass
		// such a construct as a callback to a C function.
		// It does require an executable heap. Failing that, you
		// have to pass a structure around.
		
		// Of course, all that takes a lot of code. One way to
		// make it smaller is to JSR a routine that uses the
		// return address as pointer to a list of bytes indicating
		// which stack entries to capture, and modifies the return
		// address in the process.
		
		// Against the JVM, the strategy is single-abstract-method.
	}

}
